package com.l024.hi_device_util.device;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.os.IBinder;
import android.os.IInterface;
import android.os.Looper;
import android.os.Parcel;
import android.os.RemoteException;

import java.io.IOException;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * @author wu_ming_zhi_bei
 * @date 2021/6/1 14:55
 * @Notes
 */
public class AdvertisingIdClient {

    public static final class AdInfo {

        private
        final String advertisingId;

        private
        final boolean limitAdTrackingEnabled;


        AdInfo(String advertisingId, boolean
                limitAdTrackingEnabled) {

            this.advertisingId = advertisingId;

            this.limitAdTrackingEnabled = limitAdTrackingEnabled;

        }

        public String getId() {

            return
                    this.advertisingId;

        }

        public boolean isLimitAdTrackingEnabled() {

            return
                    this.limitAdTrackingEnabled;

        }

    }

    public static AdInfo getAdvertisingIdInfo(Context context) throws Exception {

        if (Looper.myLooper() == Looper.getMainLooper())
            throw new IllegalStateException("Cannot be called from the main thread");
        try {

            PackageManager pm = context.getPackageManager();

            pm.getPackageInfo("com.android.vending", 0);

        } catch (Exception e) {
            throw e;
        }


        AdvertisingConnection connection = new
                AdvertisingConnection();

        Intent intent = new
                Intent(

                "com.google.android.gms.ads.identifier.service.START");

        intent.setPackage("com.google.android.gms");

        if
        (context.bindService(intent, connection, Context.BIND_AUTO_CREATE)) {

            try {

                AdvertisingInterface adInterface = new
                        AdvertisingInterface(

                        connection.getBinder());

                AdInfo adInfo = new
                        AdInfo(adInterface.getId(),

                        adInterface.isLimitAdTrackingEnabled(true));

                return
                        adInfo;

            } catch
            (Exception exception) {

                throw
                        exception;

            } finally {

                context.unbindService(connection);

            }

        }

        throw new IOException("Google Play connection failed");

    }


    private
    static final class AdvertisingConnection implements

            ServiceConnection {

        boolean
                retrieved = false;

        private final LinkedBlockingQueue<IBinder> queue = new LinkedBlockingQueue<>(1);


        public void onServiceConnected(ComponentName name, IBinder service) {
            try {
                this.queue.put(service);

            } catch (InterruptedException ignored) {
            }
        }


        public void onServiceDisconnected(ComponentName name) {
        }


        public IBinder getBinder() throws
                InterruptedException {

            if
            (this.retrieved)

                throw
                        new IllegalStateException();

            this.retrieved = true;

            return (IBinder) this.queue.take();

        }

    }


    private static final class AdvertisingInterface implements
            IInterface {

        private
        IBinder binder;


        public AdvertisingInterface(IBinder pBinder) {

            binder = pBinder;

        }


        public IBinder asBinder() {

            return binder;

        }


        public String getId() throws
                RemoteException {

            Parcel data = Parcel.obtain();

            Parcel reply = Parcel.obtain();

            String id;

            try {

                data.writeInterfaceToken("com.google.android.gms.ads.identifier.internal.IAdvertisingIdService");

                binder.transact(1, data, reply, 0);

                reply.readException();

                id = reply.readString();

            } finally {

                reply.recycle();

                data.recycle();

            }

            return id;

        }


        public boolean isLimitAdTrackingEnabled(boolean paramBoolean) throws
                RemoteException {

            Parcel data = Parcel.obtain();

            Parcel reply = Parcel.obtain();

            boolean limitAdTracking;

            try {

                data.writeInterfaceToken("com.google.android.gms.ads.identifier.internal.IAdvertisingIdService");

                data.writeInt(paramBoolean ? 1
                        : 0);

                binder.transact(2, data, reply, 0);

                reply.readException();

                limitAdTracking = 0
                        != reply.readInt();

            } finally {

                reply.recycle();

                data.recycle();

            }

            return limitAdTracking;

        }

    }

}